from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse, HTMLResponse
from pydantic import BaseModel
from typing import List, Optional, Dict, Any
import uvicorn
import json
import asyncio
from datetime import datetime
import psycopg2
import psycopg2.extras
import binascii
import tempfile
import os
from other.merge_and_remove_multiple_states import merge_and_remove_multiple_states
from pm4py.objects.bpmn.importer import importer as bpmn_importer
from pm4py.visualization.bpmn import visualizer as bpmn_visualizer
from pm4py.objects.bpmn.layout import layouter
from other.add_conditions_to_bpmn_flows import add_conditions_to_bpmn_flows
from other.display_bpmn_sequence import display_for_api
from other.save_bpmn_and_parse import save_bpmn_and_parse
import promoai
import requests
import time


# 网络配置 - 尝试多种连接方式
import socket

# 检查代理是否可用
def check_proxy():
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(3)
        result = sock.connect_ex(('127.0.0.1', 7890))
        sock.close()
        return result == 0
    except:
        return False

# 根据代理可用性设置环境变量
if check_proxy():
    print("检测到代理可用，使用代理连接")
    os.environ["http_proxy"] = "http://127.0.0.1:7890"
    os.environ["https_proxy"] = "http://127.0.0.1:7890"
else:
    print("代理不可用，尝试直连")
    # 清除代理设置
    if "http_proxy" in os.environ:
        del os.environ["http_proxy"]
    if "https_proxy" in os.environ:
        del os.environ["https_proxy"]

# 禁用IPv6，强制使用IPv4
os.environ["GRPC_DNS_RESOLVER"] = "native"

# 创建FastAPI应用
app = FastAPI(title="审稿流程订制系统", version="1.0.0")

# 流程数据存储 - 按processId存储流程相关信息
# 这是一个内存存储，当processId变化时，旧数据会被清理
process_storage = {}

# 配置CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 静态文件服务
app.mount("/static", StaticFiles(directory="."), name="static")

# 数据库配置 - 使用你提供的连接信息
DATABASE_CONFIG = {
    "dbname": "postgres",
    "user": "postgres", 
    "password": "Rm15127373235*",
    "host": "39.107.64.125",
    "port": "5432"
}

# AI模型配置
AI_CONFIG = {
    "api_key": "AIzaSyCyBRAwFtvPWs-IuNUoRzYJNvQEqnKjuHQ",
    "ai_model": "models/gemini-2.0-flash-lite",
    "ai_provider": "Google"
}

# 流程生成工具库
operation_description = "现在只有以下几个操作：1.选择稿件，2.获取初审意见，3.发送初审邮件，4.推荐责编，5.选择外审专家，6.接收评审意见，7.汇总评审意见，8.发送外审邮件，9.生成副终审意见，10.发送副终审邮件，11.生成终审意见，12.发送终审邮件，13.等待外审专家同意审稿。"

def get_db_connection():
    """获取数据库连接"""
    try:
        conn = psycopg2.connect(**DATABASE_CONFIG)
        return conn
    except Exception as e:
        print(f"数据库连接失败: {e}")
        raise HTTPException(status_code=500, detail="数据库连接失败")

def init_database_tables():
    """初始化数据库表"""
    # 所有表结构由数据库管理员管理，不在此处创建
    print("数据库表初始化完成 - 使用现有表结构")

def get_process_data(process_id: str):
    """获取指定流程的存储数据"""
    return process_storage.get(process_id, {})

def save_process_data(process_id: str, data: dict):
    """保存流程数据到内存存储"""
    process_storage[process_id] = data
    print(f"已保存流程 {process_id} 的数据: {list(data.keys())}")

def clear_process_data(process_id: str):
    """清理指定流程的数据"""
    if process_id in process_storage:
        del process_storage[process_id]
        print(f"已清理流程 {process_id} 的数据")

def update_process_feedback(process_id: str, feedback: str):
    """更新流程的反馈历史"""
    if process_id not in process_storage:
        process_storage[process_id] = {}
    
    if 'feedback_history' not in process_storage[process_id]:
        process_storage[process_id]['feedback_history'] = []
    
    process_storage[process_id]['feedback_history'].append(feedback)
    print(f"已添加流程 {process_id} 的反馈: {feedback[:50]}...")

# Pydantic模型
class ProcessInfo(BaseModel):
    workflow: str
    bpmn: str
    json_sequence_processed: str
    json_sequence: str

class ProcessDetail(BaseModel):
    workflow: str
    bpmn: str
    json_sequence_processed: List[Dict[str, Any]]
    json_sequence: List[Dict[str, Any]]
    flowchart_svg: Optional[str] = None

class ProcessGenerationRequest(BaseModel):
    processId: str
    description: str
    type: str

class ProcessGenerationResponse(BaseModel):
    success: bool
    message: str
    flowchart: Optional[Dict[str, Any]] = None
    sequence: Optional[List[Dict[str, Any]]] = None

class ModelGenerationRequest(BaseModel):
    processId: str
    description: str

class ModelUpdateRequest(BaseModel):
    processId: str
    description: str  # 新的反馈文本，会被添加到feedbackHistory中

class ModelResponse(BaseModel):
    success: bool
    message: str
    process_id: str  # 只返回流程ID，前端通过ID从内存获取数据

# API路由
@app.get("/")
async def read_root():
    """
    页面路由：返回前端应用首页 `index.html`。
    用于承载所有交互逻辑（流程选择、展示、定制等）。
    """
    return FileResponse("index.html")

# 角色管理API
@app.get("/api/roles")
async def get_roles():
    """
    获取所有系统角色
    - 数据来源：PostgreSQL 表 `system_role`
    - 返回：角色列表
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        cursor.execute('SELECT id, name FROM system_role ORDER BY id')
        roles = cursor.fetchall()
        return [{"id": role["id"], "name": role["name"]} for role in roles]
    except Exception as e:
        print(f"获取角色列表错误: {e}")
        return []
    finally:
        conn.close()

@app.post("/api/roles")
async def create_role(request: dict):
    """
    创建新角色
    - 检查角色名称是否已存在
    - 不存在则插入新记录
    - 存在则返回错误信息
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        role_name = request.get("name", "").strip()
        
        if not role_name:
            return {"success": False, "message": "角色名称不能为空"}
        
        # 检查角色是否已存在
        cursor.execute('SELECT id FROM system_role WHERE name = %s', (role_name,))
        existing_role = cursor.fetchone()
        
        if existing_role:
            return {"success": False, "message": f"角色 '{role_name}' 已存在"}
        
        # 插入新角色
        cursor.execute('INSERT INTO system_role (name) VALUES (%s) RETURNING id', (role_name,))
        new_role_id = cursor.fetchone()["id"]
        conn.commit()
        
        return {"success": True, "message": f"角色 '{role_name}' 创建成功", "id": new_role_id}
        
    except Exception as e:
        conn.rollback()
        print(f"创建角色错误: {e}")
        return {"success": False, "message": f"创建角色失败: {str(e)}"}
    finally:
        conn.close()

@app.delete("/api/roles/{role_id}")
async def delete_role(role_id: int):
    """
    删除角色
    - 根据角色ID删除记录
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        
        # 检查角色是否存在
        cursor.execute('SELECT name FROM system_role WHERE id = %s', (role_id,))
        role = cursor.fetchone()
        
        if not role:
            return {"success": False, "message": "角色不存在"}
        
        # 删除角色
        cursor.execute('DELETE FROM system_role WHERE id = %s', (role_id,))
        conn.commit()
        
        return {"success": True, "message": f"角色 '{role['name']}' 删除成功"}
        
    except Exception as e:
        conn.rollback()
        print(f"删除角色错误: {e}")
        return {"success": False, "message": f"删除角色失败: {str(e)}"}
    finally:
        conn.close()

# 系统阶段定制API
@app.get("/api/workflow-stages")
async def get_workflow_stages():
    """
    获取所有系统阶段
    - 数据来源：PostgreSQL 表 `system_workflow_stage`
    - 返回：阶段列表
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        print("正在查询system_workflow_stage表...")
        cursor.execute('SELECT id, name, role, status FROM system_workflow_stage ORDER BY id')
        stages = cursor.fetchall()
        print(f"查询到 {len(stages)} 个阶段: {stages}")
        
        result = [{"id": stage["id"], "name": stage["name"], "role": stage["role"], "status": stage["status"]} for stage in stages]
        print(f"返回结果: {result}")
        return result
    except Exception as e:
        print(f"获取阶段列表错误: {e}")
        import traceback
        traceback.print_exc()
        return []
    finally:
        conn.close()

@app.post("/api/workflow-stages")
async def create_workflow_stage(request: dict):
    """
    创建新阶段
    - 检查阶段名称是否已存在
    - 不存在则插入新记录
    - 存在则返回错误信息
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        stage_name = request.get("name", "").strip()
        stage_role = request.get("role", "").strip()
        
        if not stage_name:
            return {"success": False, "message": "阶段名称不能为空"}
        
        if not stage_role:
            return {"success": False, "message": "角色不能为空"}
        
        # 检查阶段是否已存在
        cursor.execute('SELECT id FROM system_workflow_stage WHERE name = %s', (stage_name,))
        existing_stage = cursor.fetchone()
        
        if existing_stage:
            return {"success": False, "message": f"阶段 '{stage_name}' 已存在"}
        
        # 插入新阶段（包含角色信息）
        cursor.execute('INSERT INTO system_workflow_stage (name, role, enabled) VALUES (%s, %s, %s) RETURNING id', (stage_name, stage_role, False))
        new_stage_id = cursor.fetchone()["id"]
        conn.commit()
        
        return {"success": True, "message": f"阶段 '{stage_name}' 创建成功，角色：{stage_role}", "id": new_stage_id}
        
    except Exception as e:
        conn.rollback()
        print(f"创建阶段错误: {e}")
        return {"success": False, "message": f"创建阶段失败: {str(e)}"}
    finally:
        conn.close()

@app.delete("/api/workflow-stages/{stage_id}")
async def delete_workflow_stage(stage_id: int):
    """
    删除阶段
    - 根据阶段ID删除记录
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        
        # 检查阶段是否存在
        cursor.execute('SELECT name FROM system_workflow_stage WHERE id = %s', (stage_id,))
        stage = cursor.fetchone()
        
        if not stage:
            return {"success": False, "message": "阶段不存在"}
        
        # 删除阶段
        cursor.execute('DELETE FROM system_workflow_stage WHERE id = %s', (stage_id,))
        conn.commit()
        
        return {"success": True, "message": f"阶段 '{stage['name']}' 删除成功"}
        
    except Exception as e:
        conn.rollback()
        print(f"删除阶段错误: {e}")
        return {"success": False, "message": f"删除阶段失败: {str(e)}"}
    finally:
        conn.close()

# 更新阶段审稿结果API
@app.post("/api/workflow-stages/update-status")
async def update_stage_status(request: dict):
    """
    更新阶段的审稿结果
    - 将新的审稿结果添加到现有结果中（用、分隔）
    - 如果status字段为空，则直接设置
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        stage_id = request.get("stageId")
        new_status = request.get("status", "").strip()
        
        if not stage_id:
            return {"success": False, "message": "阶段ID不能为空"}
        
        if not new_status:
            return {"success": False, "message": "审稿结果不能为空"}
        
        # 获取当前阶段的审稿结果
        cursor.execute('SELECT name, status FROM system_workflow_stage WHERE id = %s', (stage_id,))
        stage = cursor.fetchone()
        
        if not stage:
            return {"success": False, "message": "阶段不存在"}
        
        current_status = stage["status"] or ""
        
        # 如果当前状态为空，直接设置新状态
        if not current_status:
            updated_status = new_status
        else:
            # 检查是否已存在相同的审稿结果
            if new_status in current_status.split('、'):
                return {"success": False, "message": f"审稿结果 '{new_status}' 已存在"}
            # 添加新的审稿结果
            updated_status = current_status + '、' + new_status
        
        # 更新数据库
        cursor.execute('UPDATE system_workflow_stage SET status = %s WHERE id = %s', (updated_status, stage_id))
        conn.commit()
        
        return {"success": True, "message": f"阶段 '{stage['name']}' 的审稿结果已更新：{updated_status}"}
        
    except Exception as e:
        conn.rollback()
        print(f"更新审稿结果错误: {e}")
        return {"success": False, "message": f"更新审稿结果失败: {str(e)}"}
    finally:
        conn.close()

# 清空阶段审稿结果API
@app.post("/api/workflow-stages/clear-status")
async def clear_stage_status(request: dict):
    """
    清空阶段的审稿结果
    - 将status字段设置为NULL
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        stage_id = request.get("stageId")
        
        if not stage_id:
            return {"success": False, "message": "阶段ID不能为空"}
        
        # 获取阶段名称
        cursor.execute('SELECT name FROM system_workflow_stage WHERE id = %s', (stage_id,))
        stage = cursor.fetchone()
        
        if not stage:
            return {"success": False, "message": "阶段不存在"}
        
        # 清空审稿结果
        cursor.execute('UPDATE system_workflow_stage SET status = NULL WHERE id = %s', (stage_id,))
        conn.commit()
        
        return {"success": True, "message": f"阶段 '{stage['name']}' 的审稿结果已清空"}
        
    except Exception as e:
        conn.rollback()
        print(f"清空审稿结果错误: {e}")
        return {"success": False, "message": f"清空审稿结果失败: {str(e)}"}
    finally:
        conn.close()

# 系统状态定制API
@app.get("/api/statuses")
async def get_statuses():
    """
    获取所有系统状态
    - 数据来源：PostgreSQL 表 `system_status`
    - 返回：状态列表
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        cursor.execute('SELECT id, name FROM system_status ORDER BY id')
        statuses = cursor.fetchall()
        return [{"id": status["id"], "name": status["name"]} for status in statuses]
    except Exception as e:
        print(f"获取状态列表错误: {e}")
        return []
    finally:
        conn.close()

@app.post("/api/statuses")
async def create_status(request: dict):
    """
    创建新状态
    - 检查状态名称是否已存在
    - 不存在则插入新记录
    - 存在则返回错误信息
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        status_name = request.get("name", "").strip()
        
        if not status_name:
            return {"success": False, "message": "状态名称不能为空"}
        
        # 检查状态是否已存在
        cursor.execute('SELECT id FROM system_status WHERE name = %s', (status_name,))
        existing_status = cursor.fetchone()
        
        if existing_status:
            return {"success": False, "message": f"状态 '{status_name}' 已存在"}
        
        # 插入新状态
        cursor.execute('INSERT INTO system_status (name) VALUES (%s) RETURNING id', (status_name,))
        new_status_id = cursor.fetchone()["id"]
        conn.commit()
        
        return {"success": True, "message": f"状态 '{status_name}' 创建成功", "id": new_status_id}
        
    except Exception as e:
        conn.rollback()
        print(f"创建状态错误: {e}")
        return {"success": False, "message": f"创建状态失败: {str(e)}"}
    finally:
        conn.close()

@app.delete("/api/statuses/{status_id}")
async def delete_status(status_id: int):
    """
    删除状态
    - 根据状态ID删除记录
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        
        # 检查状态是否存在
        cursor.execute('SELECT name FROM system_status WHERE id = %s', (status_id,))
        status = cursor.fetchone()
        
        if not status:
            return {"success": False, "message": "状态不存在"}
        
        # 删除状态
        cursor.execute('DELETE FROM system_status WHERE id = %s', (status_id,))
        conn.commit()
        
        return {"success": True, "message": f"状态 '{status['name']}' 删除成功"}
        
    except Exception as e:
        conn.rollback()
        print(f"删除状态错误: {e}")
        return {"success": False, "message": f"删除状态失败: {str(e)}"}
    finally:
        conn.close()

# 更新系统阶段启用状态API
@app.post("/api/workflow-stages/update-enabled")
async def update_workflow_stages_enabled(request: dict):
    """
    更新系统阶段的启用状态
    - 将选中的阶段enabled置为true
    - 将未选中的阶段enabled置为false
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        selected_stage_ids = request.get("selectedStageIds", [])
        
        if not selected_stage_ids:
            return {"success": False, "message": "请至少选择一个阶段"}
        
        # 首先将所有阶段的enabled置为false
        cursor.execute('UPDATE system_workflow_stage SET enabled = false')
        
        # 然后将选中的阶段enabled置为true
        if selected_stage_ids:
            placeholders = ','.join(['%s'] * len(selected_stage_ids))
            cursor.execute(f'UPDATE system_workflow_stage SET enabled = true WHERE id IN ({placeholders})', selected_stage_ids)
        
        conn.commit()
        
        # 获取更新后的阶段信息
        cursor.execute('SELECT id, name, enabled FROM system_workflow_stage ORDER BY id')
        stages = cursor.fetchall()
        
        enabled_stages = [stage for stage in stages if stage['enabled']]
        disabled_stages = [stage for stage in stages if not stage['enabled']]
        
        return {
            "success": True, 
            "message": f"成功更新阶段状态：启用 {len(enabled_stages)} 个，禁用 {len(disabled_stages)} 个",
            "enabledStages": [{"id": stage["id"], "name": stage["name"]} for stage in enabled_stages],
            "disabledStages": [{"id": stage["id"], "name": stage["name"]} for stage in disabled_stages]
        }
        
    except Exception as e:
        conn.rollback()
        print(f"更新阶段启用状态错误: {e}")
        return {"success": False, "message": f"更新阶段状态失败: {str(e)}"}
    finally:
        conn.close()

@app.get("/api/processes/available")
async def get_available_processes():
    """
    获取所有可用流程
    - 数据来源：PostgreSQL 表 `system_workflow_stage`
    - 返回：流程名称列表
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        cursor.execute('SELECT id, name FROM system_workflow_stage ORDER BY id')
        processes = cursor.fetchall()
        return [{"id": process["id"], "name": process["name"]} for process in processes]
    except Exception as e:
        print(f"获取可用流程列表错误: {e}")
        return []
    finally:
        conn.close()

@app.get("/api/workflow-config")
async def get_workflow_config():
    """
    获取工作流配置
    - 返回所有阶段的启用状态
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        cursor.execute('SELECT id, name, enabled FROM system_workflow_stage ORDER BY id')
        stages = cursor.fetchall()
        
        return [{"id": stage["id"], "name": stage["name"], "enable": stage["enabled"]} for stage in stages]
        
    except Exception as e:
        print(f"获取工作流配置错误: {e}")
        return []
    finally:
        conn.close()

@app.post("/api/workflow-config/update")
async def update_workflow_config(request: dict):
    """
    更新工作流配置
    - 将选中的阶段enabled置为true
    - 将未选中的阶段enabled置为false
    - 输入：选中的阶段名称列表
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        selected_stage_names = request.get("selectedStageNames", [])
        
        if not selected_stage_names:
            return {"success": False, "message": "请至少选择一个阶段"}
        
        # 首先将所有阶段的enabled置为false
        cursor.execute('UPDATE system_workflow_stage SET enabled = false')
        
        # 然后将选中的阶段enabled置为true
        if selected_stage_names:
            placeholders = ','.join(['%s'] * len(selected_stage_names))
            cursor.execute(f'UPDATE system_workflow_stage SET enabled = true WHERE name IN ({placeholders})', selected_stage_names)
        
        conn.commit()
        
        # 获取更新后的阶段信息
        cursor.execute('SELECT id, name, enabled FROM system_workflow_stage ORDER BY id')
        stages = cursor.fetchall()
        
        enabled_stages = [stage for stage in stages if stage['enabled']]
        disabled_stages = [stage for stage in stages if not stage['enabled']]
        
        return {
            "success": True, 
            "message": f"成功更新工作流配置：启用 {len(enabled_stages)} 个阶段，禁用 {len(disabled_stages)} 个阶段",
            "enabledStages": [{"id": stage["id"], "name": stage["name"]} for stage in enabled_stages],
            "disabledStages": [{"id": stage["id"], "name": stage["name"]} for stage in disabled_stages]
        }
        
    except Exception as e:
        conn.rollback()
        print(f"更新工作流配置错误: {e}")
        return {"success": False, "message": f"更新工作流配置失败: {str(e)}"}
    finally:
        conn.close()

@app.get("/api/processes/existing")
async def get_existing_processes():
    """
    数据API：获取所有已定制的流程，返回卡片展示所需的完整数据。
    - 数据来源：PostgreSQL 表 `bpmn_sequence`
    - 返回：每个流程的 SVG 流程图 + 规整后的流程序列
    - 用途：前端“局部更改流程”区域卡片渲染
    """
    conn = get_db_connection()
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
        
        # 先检查表是否存在
        cursor.execute("""
            SELECT EXISTS (
                SELECT FROM information_schema.tables 
                WHERE table_name = 'bpmn_sequence'
            );
        """)
        table_exists = cursor.fetchone()['exists']
        print(f"bpmn_sequence表存在: {table_exists}")
        
        if not table_exists:
            print("bpmn_sequence表不存在")
            return []
        
        # 检查表中有多少数据
        cursor.execute('SELECT COUNT(*) FROM bpmn_sequence')
        count = cursor.fetchone()['count']
        print(f"bpmn_sequence表中数据条数: {count}")
        
        if count == 0:
            print("bpmn_sequence表中没有数据")
            return []
        
        cursor.execute('SELECT workflow, bpmn, json_sequence_processed, json_sequence FROM bpmn_sequence ORDER BY workflow')
        rows = cursor.fetchall()
        print(f"查询到 {len(rows)} 条记录")
        
        if len(rows) == 0:
            print("查询结果为空")
            return []
        
        # 转换为display_for_api函数需要的格式
        display_rows = [(row["workflow"], row["bpmn"], row["json_sequence_processed"], row["json_sequence"]) for row in rows]
        print(f"转换后的数据行数: {len(display_rows)}")
        
        # 调用display_for_api函数处理数据
        processed_flows = display_for_api(display_rows)
        print(f"处理后的流程数: {len(processed_flows)}")
        
        return processed_flows
    except Exception as e:
        print(f"数据库查询错误: {e}")
        import traceback
        traceback.print_exc()
        return []  # 返回空列表而不是抛出异常
    finally:
        conn.close()






def generate_bpmn_svg(bpmn_data: str, json_sequence: List[Dict[str, Any]]) -> str:
    """从数据库读出来字符串数据后生成BPMN流程图的SVG"""
    try:
        # 处理十六进制或二进制数据
        if isinstance(bpmn_data, str) and bpmn_data.startswith('\\x'):
            bytes_bpmn = binascii.unhexlify(bpmn_data[2:])
        elif isinstance(bpmn_data, (bytes, bytearray)):
            bytes_bpmn = bpmn_data
        else:
            bytes_bpmn = bpmn_data.encode('utf-8')

        xml_bpmn = bytes_bpmn.decode('utf-8').strip()

        # XML → BPMN 对象
        with tempfile.NamedTemporaryFile(delete=False, suffix=".bpmn") as tmp:
            tmp.write(xml_bpmn.encode("utf-8"))
            tmp_path = tmp.name
        
        bpmn_obj = bpmn_importer.apply(tmp_path)
        
        # 增加条件标签
        hits = add_conditions_to_bpmn_flows(bpmn_obj, json_sequence)

        # Layout & 可视化
        image_format = "svg"
        layouted_bpmn = layouter.apply(bpmn_obj)
        visualization = bpmn_visualizer.apply(
            layouted_bpmn, parameters={"format": image_format}
        )
        vis_str = visualization.pipe(format="svg").decode("utf-8")
        
        # 清理临时文件
        os.unlink(tmp_path)
        
        return vis_str
        
    except Exception as e:
        print(f"生成BPMN SVG失败: {e}")
        return f"<svg><text>流程图生成失败: {str(e)}</text></svg>"


@app.post("/api/processes/clear-process/{process_id}")
async def clear_process(process_id: str):
    """
    清理指定流程的数据
    - 当用户切换流程时调用，清理旧流程的数据
    """
    try:
        clear_process_data(process_id)
        return {"success": True, "message": f"流程 {process_id} 数据已清理"}
    except Exception as e:
        return {"success": False, "message": f"清理失败: {str(e)}"}

@app.get("/api/processes/storage-status")
async def get_storage_status():
    """
    获取当前存储状态（调试用）
    """
    return {
        "total_processes": len(process_storage),
        "processes": list(process_storage.keys()),
        "storage_details": {
            process_id: {
                "has_model": "process_model" in data,
                "has_bpmn": "bpmn" in data,
                "feedback_count": len(data.get("feedback_history", [])),
                "created_at": data.get("created_at"),
                "last_updated": data.get("last_updated")
            }
            for process_id, data in process_storage.items()
        }
    }


@app.get("/api/processes/{process_id}/data")
async def get_process_data_api(process_id: str):
    """
    获取指定流程的数据（前端调用）
    """
    try:
        process_data = get_process_data(process_id)
        if not process_data:
            return {"success": False, "message": f"流程 {process_id} 不存在"}
        
        # 直接读取内存中存储的流程图SVG
        flowchart_svg = process_data.get("flowchart_svg")
        sequence_data = process_data.get("updated_sequence", [])
        
        if not flowchart_svg:
            flowchart_svg = "<svg><text>流程图未找到</text></svg>"
        
        return {
            "success": True,
            "process_id": process_id,
            "flowchart": flowchart_svg,
            "sequence": sequence_data,
            "feedback_count": len(process_data.get("feedback_history", [])),
            "created_at": process_data.get("created_at"),
            "last_updated": process_data.get("last_updated")
        }
        
    except Exception as e:
        return {"success": False, "message": f"获取流程数据失败: {str(e)}"}

@app.post("/api/processes/{process_id}/update-sequence")
async def update_sequence_data(process_id: str, request: dict):
    """
    更新流程的序列数据
    """
    try:
        sequence_data = request.get("sequence", [])
        if not sequence_data:
            return {"success": False, "message": "序列数据不能为空"}
        
        # 更新内存存储中的序列数据
        process_data = get_process_data(process_id)
        if not process_data:
            return {"success": False, "message": f"流程 {process_id} 不存在"}
        
        # 更新序列数据
        process_data["updated_sequence"] = sequence_data
        save_process_data(process_id, process_data)
        
        return {"success": True, "message": "序列数据更新成功"}
        
    except Exception as e:
        return {"success": False, "message": f"更新序列数据失败: {str(e)}"}

@app.post("/api/processes/save-model")
async def save_model_to_db(request: dict):
    """
    保存模型到数据库
    """
    try:
        process_id = request.get("processId")
        if not process_id:
            return {"success": False, "message": "流程ID不能为空"}
        
        # 获取流程数据
        process_data = get_process_data(process_id)
        if not process_data:
            return {"success": False, "message": f"流程 {process_id} 不存在"}
        
        # 获取BPMN和序列数据
        bpmn = process_data.get("bpmn")
        sequence_json_processed = process_data.get("updated_sequence", [])
        sequence_json = process_data.get("sequence_json", [])
        
        if not bpmn:
            return {"success": False, "message": "BPMN数据不存在"}
        
        if not sequence_json_processed:
            return {"success": False, "message": "序列数据不存在"}
        
        # 导入保存函数
        from other.app_save_model import save_workflow_to_db
        
        # 使用统一的数据库配置
        database = DATABASE_CONFIG
        
        # 保存到数据库
        save_workflow_to_db(bpmn, sequence_json_processed, sequence_json, process_id, database)
        
        print(f"流程 {process_id} 已保存到数据库")
        
        return {
            "success": True,
            "message": f"流程 {process_id} 保存成功"
        }
        
    except Exception as e:
        print(f"保存模型失败: {str(e)}")
        import traceback
        traceback.print_exc()
        return {"success": False, "message": f"保存失败: {str(e)}"}

@app.post("/api/processes/generate-model", response_model=ModelResponse)
async def generate_model(request: ModelGenerationRequest):
    """
    生成API：调用promoai.generate_model_from_text生成新模型。
    - 输入：流程ID + 描述文本
    - 返回：生成的模型 + 流程图 + 序列
    """
    try:
        # 1. 调用promoai生成模型
        
        print("开始生成模型...")
        
        # 构建带工具库约束的描述
        constrained_description = f"{operation_description}请只使用以上13个操作，生成流程。以下是对流程{request.processId}的描述：{request.description}"
        
        process_model = promoai.generate_model_from_text(
            constrained_description,
            api_key=AI_CONFIG["api_key"],
            ai_model=AI_CONFIG["ai_model"],
            ai_provider=AI_CONFIG["ai_provider"]
        )
        print(f"模型生成完成，类型: {type(process_model)}")
        
        # 2. 调用save_bpmn_and_parse生成调整后的bpmn对象和流程序列
        print(f"解析BPMN和流程序列...")
        bpmn, sequence_df, sequence_json = save_bpmn_and_parse(process_model)
        
        # 3. 调用工作流更新流程序列
        print(f"调用工作流更新流程序列...")
        webhook_url = "http://39.107.64.125:5678/webhook/6f821ff6-84e1-4b6c-a240-dc145410ab60"
        payload = {
            "sequence_feedback": [],  # 首次生成时为空
            "sequence_json": json.dumps(sequence_json, ensure_ascii=False, indent=2),
            "description": request.description
        }

        #print(f"发送webhook请求到: {webhook_url}")
        #print(f"请求数据大小: {len(json.dumps(payload))} 字节")
        
        try:
            response = requests.post(webhook_url, json=payload, timeout=180)
        except requests.exceptions.Timeout as e:
            print(f"Webhook请求超时: {e}")
            print("重试一次...")
            response = requests.post(webhook_url, json=payload, timeout=180)
        except requests.exceptions.RequestException as e:
            print(f"Webhook请求异常: {e}")
            return ModelResponse(success=False, message=f"工作流调用失败: {str(e)}", process_id=request.processId)
        
        # 如果第一次失败，重试一次
        if response.status_code != 200:
            print("第一次webhook请求失败，重试一次...")
            try:
                response = requests.post(webhook_url, json=payload, timeout=180)
                print(f"重试后Webhook状态码: {response.status_code}")
            except requests.exceptions.RequestException as e:
                print(f"重试Webhook请求异常: {e}")
                return ModelResponse(success=False, message=f"工作流重试失败: {str(e)}", process_id=request.processId)
        
        # 处理webhook响应
        if response.status_code == 200:
            try:
                data = response.json()
                sequence_json = data.get("workflow_list", [])
                print("增加条件和参数后",sequence_json)
                sequence_data = merge_and_remove_multiple_states(sequence_json)
                #print(f"工作流更新成功，获得 {len(sequence_data)} 条序列数据")
                
            except Exception as e:
                print(f"Webhook返回不是合法JSON: {e}, 使用原始序列数据")
                sequence_data = sequence_json
        else:
            print(f"Webhook请求失败，使用原始序列数据")
            sequence_data = sequence_json
        
        print("#######增加条件和参数后",sequence_json)
        #  生成流程图SVG
        hits = add_conditions_to_bpmn_flows(bpmn, sequence_json)
        image_format = "svg"
        layouted_bpmn = layouter.apply(bpmn)
        visualization = bpmn_visualizer.apply(
            layouted_bpmn, parameters={"format": image_format}
        )
        flowchart_svg = visualization.pipe(format="svg").decode("utf-8")
        # 存储流程数据到内存
        process_data = {  
            "process_model": process_model,  # 存储POWL对象
            "bpmn": bpmn,                   # 存储BPMN对象
            "sequence_df": sequence_df,      # 存储序列DataFrame
            "sequence_json": sequence_json,  # 存储增加条件和参数后原始序列JSON
            "updated_sequence": sequence_data,  # 存储增加条件和参数并删除控制节点的序列
            "flowchart_svg": flowchart_svg,  # 存储流程图SVG
            "feedback_history": [],  # 初次生成时为空，不包含初始描述
            "created_at": datetime.now().isoformat(),
            "last_updated": datetime.now().isoformat()
        }
        
        # 保存到内存存储
        save_process_data(request.processId, process_data)
        
    
        
        
        print(f"流程 {request.processId} 模型生成完成")
        
        return ModelResponse(
            success=True,
            message="模型生成成功",
            process_id=request.processId
        )
        
    except Exception as e:
        print(f"模型生成失败: {str(e)}")
        import traceback
        traceback.print_exc()
        return ModelResponse(success=False, message=f"模型生成失败: {str(e)}", process_id=request.processId)

@app.post("/api/processes/update-model", response_model=ModelResponse)
async def update_model(request: ModelUpdateRequest):
    """
    更新API：调用promoai的update方法更新现有模型。
    - 输入：流程ID + 新描述 + 现有模型 + 反馈历史
    - 返回：更新后的模型 + 流程图 + 序列
    """
    try:
        # 1. 从内存存储中获取流程数据
        process_data = get_process_data(request.processId)
        if not process_data:
            return ModelResponse(success=False, message=f"流程 {request.processId} 不存在，请先生成模型", process_id=request.processId)
        
        # 2. 获取存储的POWL模型对象
        process_model = process_data.get("process_model")
        if not process_model:
            return ModelResponse(success=False, message="POWL模型对象不存在", process_id=request.processId)
        
        print(f"开始更新流程 {request.processId} 的模型...")
        
        # 3. 先将新的描述加入feedback历史
        current_feedback = process_data.get("feedback_history", [])
        current_feedback.append(request.description)
        
        # 4. 调用promoai更新模型，将feedback列表转换为字符串
        feedback_text = "\n".join(current_feedback)  # 将列表转换为字符串，用换行符连接
        process_model.update(
            feedback_text,  # 传入字符串格式的feedback
            api_key=AI_CONFIG["api_key"],
            ai_model=AI_CONFIG["ai_model"],
            ai_provider=AI_CONFIG["ai_provider"]
        )
        
        # 4. 保存并解析更新后的BPMN
        print(f"解析更新后的BPMN和流程序列...")
        bpmn, sequence_df, sequence_json = save_bpmn_and_parse(process_model)
        
        # 5. 调用工作流更新流程序列
        print(f"调用工作流更新流程序列...")
        webhook_url = "http://39.107.64.125:5678/webhook/6f821ff6-84e1-4b6c-a240-dc145410ab60"
        payload = {
            "sequence_feedback": current_feedback,  # 使用更新后的feedback列表
            "sequence_json": json.dumps(sequence_json, ensure_ascii=False, indent=2),
            "description": request.description
        }
        
        #print(f"发送webhook请求到: {webhook_url}")
        #print(f"请求数据大小: {len(json.dumps(payload))} 字节")
        
        try:
            response = requests.post(webhook_url, json=payload, timeout=180)
        except requests.exceptions.Timeout as e:
            print(f"Webhook请求超时: {e}")
            print("重试一次...")
            response = requests.post(webhook_url, json=payload, timeout=180)
            print(f"重试后Webhook状态码: {response.status_code}")
        except requests.exceptions.RequestException as e:
            print(f"Webhook请求异常: {e}")
            return ModelResponse(success=False, message=f"工作流调用失败: {str(e)}", process_id=request.processId)
        
        # 如果第一次失败，重试一次
        if response.status_code != 200:
            print("第一次webhook请求失败，重试一次...")
            try:
                response = requests.post(webhook_url, json=payload, timeout=180)
                print(f"重试后Webhook状态码: {response.status_code}")
            except requests.exceptions.RequestException as e:
                print(f"重试Webhook请求异常: {e}")
                return ModelResponse(success=False, message=f"工作流重试失败: {str(e)}", process_id=request.processId)
        
        # 处理webhook响应
        if response.status_code == 200:
            try:
                data = response.json()
                sequence_json = data.get("workflow_list", [])
                print("增加条件和参数后",sequence_json)
                sequence_data = merge_and_remove_multiple_states(sequence_json)
                #print(f"工作流更新成功，获得 {len(sequence_data)} 条序列数据")
                
            except Exception as e:
                print(f"Webhook返回不是合法JSON: {e}, 使用原始序列数据")
                sequence_data = sequence_json
        else:
            print(f"Webhook请求失败，使用原始序列数据")
            sequence_data = sequence_json
        
        print("#######增加条件和参数后",sequence_json)
        # . 生成流程图SVG
        hits = add_conditions_to_bpmn_flows(bpmn, sequence_json)
        image_format = "svg"
        layouted_bpmn = layouter.apply(bpmn)
        visualization = bpmn_visualizer.apply(
            layouted_bpmn, parameters={"format": image_format}
        )
        flowchart_svg = visualization.pipe(format="svg").decode("utf-8")
        # 6. 更新流程数据到内存存储
        process_data.update({
            "process_model": process_model,  # 更新POWL对象
            "bpmn": bpmn,                   # 更新BPMN对象
            "sequence_df": sequence_df,      # 更新序列DataFrame
            "sequence_json": sequence_json,  # 存储增加条件和参数后原始序列JSON
            "updated_sequence": sequence_data,  # 存储增加条件和参数并删除控制节点的序列
            "flowchart_svg": flowchart_svg,  # 更新流程图SVG
            "feedback_history": current_feedback,  # 更新feedback历史
            "last_updated": datetime.now().isoformat()
        })
        
        # 保存更新后的数据
        save_process_data(request.processId, process_data)
        
        
        
        print(f"流程 {request.processId} 模型更新完成")
        
        return ModelResponse(
            success=True,
            message="模型更新成功",
            process_id=request.processId
        )
        
    except Exception as e:
        print(f"模型更新失败: {str(e)}")
        import traceback
        traceback.print_exc()
        return ModelResponse(success=False, message=f"模型更新失败: {str(e)}", process_id=request.processId)

if __name__ == "__main__":
    # 初始化数据库表
    init_database_tables()
    
    uvicorn.run(
        app, 
        host="0.0.0.0", 
        port=8000,
        timeout_keep_alive=400,  # 保持连接400秒（超过3分钟）
        timeout_graceful_shutdown=30  # 优雅关闭30秒
    )
